/* Copyright 2007 Ryan Phillips.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include "xblf.h"
#include "xblf_private.h"

size_t xblf_write_callback(void *ptr, size_t size, size_t nmemb,
                           void *userdata)
{
    xblf_friend_t *f = (xblf_friend_t*)userdata;
    int len = size * nmemb;
    int rc = 0;

    f->total_bytes += len;

    if (!f->xc) {
        f->xc = xmlCreatePushParserCtxt(NULL, NULL, 
                                        (const char*)ptr, len,
                                        (const char*)f->uri);
        
        if (f->xc) {
            f->xc->replaceEntities = 1;
            f->xc->loadsubset = 1;
        }
    }
    else {
        xmlParseChunk(f->xc, (const char*)ptr, len, 0);
    }

    return len;
}

char* xblf_xpath_eval(xblf_friend_t *f, xmlXPathContextPtr xpath_ctx, 
                    const xmlChar *xpath_expr)
{
    /* Courtesy flickcurl */
    xmlXPathObjectPtr xpathObj=NULL;
    xmlNodeSetPtr nodes;
    int i;
    char* value=NULL;

    xpathObj = xmlXPathEvalExpression(xpath_expr, xpath_ctx);
    if(!xpathObj) {
        goto tidy;
    }

    nodes=xpathObj->nodesetval;
    for(i=0; i < xmlXPathNodeSetGetLength(nodes); i++) {
        xmlNodePtr node=nodes->nodeTab[i];

        if(node->type != XML_ATTRIBUTE_NODE &&
           node->type != XML_ELEMENT_NODE) {
            break;
        }    
        if(node->children)
            value=strdup((char*)node->children->content);
        break;
    }

tidy:
    if(xpathObj)
        xmlXPathFreeObject(xpathObj);

    return value;
}

xblf_recentgames_t** 
xblf_build_recentgames(xblf_friend_t *f, xmlXPathContextPtr xpath_ctx,
                    const xmlChar* xpath_expr, int *count_p)
{
    xmlXPathObjectPtr xpathObj=NULL;
    xmlNodeSetPtr nodes;
    int nodes_count;
    int recentgame_count;
    int i;
    xblf_recentgames_t **recentgames = NULL;

    xpathObj = xmlXPathEvalExpression(xpath_expr, xpath_ctx);
    if(!xpathObj) {
        goto tidy;
    }

    nodes = xpathObj->nodesetval;
    nodes_count = xmlXPathNodeSetGetLength(nodes);
    recentgames = (xblf_recentgames_t**) calloc(sizeof(xblf_recentgames_t*), nodes_count+1);
    recentgame_count = 0;

    for (i=0; i<nodes_count; i++) {
        xmlNodePtr node = nodes->nodeTab[i];
        xmlNodePtr child_node;

        xblf_recentgames_t *recgame = (xblf_recentgames_t*) calloc(sizeof(xblf_recentgames_t), 1);

        for (child_node=node->children; child_node; child_node=child_node->next) {
            if (child_node->type == XML_ELEMENT_NODE) {
                const char *child_name = child_node->name;
                if (strcmp(child_name, "Game") == 0) {
                    /* Parse Game Node */
                    xmlNodePtr game_child;
                    for (game_child=child_node->children; game_child; game_child=game_child->next) {
                        if (game_child->type == XML_ELEMENT_NODE) {
                            const char *name = game_child->name;
                            char *data = game_child->children->content;

                            if (!strcmp(name, "Name")) {
                                recgame->game.name = strdup(data);
                            }
                            else if (!strcmp(name, "TotalAchievements")) {
                                recgame->game.total_achievements = atoi(data);
                            }
                            else if (!strcmp(name, "TotalGameScore")) {
                                recgame->game.total_gamescore = atoi(data);
                            }
                            else if (!strcmp(name, "Image32Url")) {
                                recgame->game.image_32url = strdup(data);
                            }
                            else if (!strcmp(name, "Image64Url")) {
                                recgame->game.image_64url = strdup(data);
                            }
                        }
                    }
                }
                else {
                    char *value = malloc(strlen(child_node->children->content) + 1);
                    strcpy(value, child_node->children->content);

                    if (!strcmp(child_name, "LastPlayed")) {
                        recgame->last_played = value;
                    }
                    else if (!strcmp(child_name, "Achievements")) {
                        recgame->achievements = atoi(value);
                        free(value);
                    }
                    else if (!strcmp(child_name, "GamerScore")) {
                        recgame->gamerscore = atoi(value);
                        free(value);
                    }
                    else if (!strcmp(child_name, "DetailsURL")) {
                        recgame->details_url = value;
                    }
                }
            }
        }

        recentgames[recentgame_count++] = recgame;
    }

tidy:
    if(xpathObj)
        xmlXPathFreeObject(xpathObj);

    return recentgames;
}

